package cn.edu.nju.ws.sview.views.data;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.AbstractMap.SimpleEntry;
import java.util.Map.Entry;

import cn.edu.nju.ws.sview.database.DBConnectionFactory;
import cn.edu.nju.ws.sview.views.Entity;
import cn.edu.nju.ws.sview.views.data.EntityBrowsing.QuadItem;

abstract class RelateRecomm extends RecommandSrc{
	protected int itemType;
	public RelateRecomm(RecType t,String lang){
		super(t, lang);
		if(t == RecType.CUST_ENTITY_RELATION_BASED)
			this.itemType = 1;
		else if(t == RecType.URI_RELATION_BASED)
			this.itemType = 2;
		else
			this.itemType = 3;
	}
	protected HashMap<Integer, Integer> getCandidates(int itemId){
		HashMap<Integer, Integer> ret = new HashMap<Integer, Integer>();
		HashSet<Integer> uris = Entity.getMembersByEntityId(itemId);
		for(int uri : uris){
			HashSet<Integer> entities = Entity.getEntitiesHavingURIByBookmark(uri, this.itemType, this.lang);
			for(int en : entities){
				if(en == itemId)
					continue;
				int key = Entity.getMembersByEntityId(en).size();
				ret.put(en, key);
			}
		}
		return ret;
	}
}
class NComparator implements Comparator<Entry<Integer, Integer>>{
	@Override
	public int compare(Entry<Integer, Integer> o1,
			Entry<Integer, Integer> o2) {
		// TODO Auto-generated method stub
		int a = o1.getValue(), b = o2.getValue();
		if(a > b)
			return -1;
		if(a < b)
			return 1;
		return 0;
	}

	
}
public class CustEntityRelateRecomm extends RelateRecomm{

	protected CustEntityRelateRecomm(String l) {
		super(RecType.CUST_ENTITY_RELATION_BASED, l);
		// TODO Auto-generated constructor stub
	}

	@Override
	public LinkedList<QuadItem> getRecommandItems(int itemId, int itemType, int requiredNum)
			throws Exception {
		HashMap<Integer, Integer> items = this.getCandidates(itemId);
		if(items.size() == 0)
			return new LinkedList<QuadItem>();
		String itemIds = "";
		for(int id : items.keySet()){
			itemIds += id + ",";
		}
		itemIds = itemIds.substring(0, itemIds.length() - 1);
		LinkedList<QuadItem> ret = new LinkedList<QuadItem>();
		HashMap<Integer, Integer> itemTimes = new HashMap<Integer, Integer>();
		try{
			Connection con = DBConnectionFactory.getConnection();
			PreparedStatement ps = con.prepareStatement("SELECT member_id , SUM(times_recent) FROM user_day_visit " +
				"WHERE member_type = 1 AND member_id in (" + itemIds + ") GROUP BY member_id ORDER BY SUM(times_recent) DESC;");
			ResultSet rs = ps.executeQuery();
			while(rs.next()){
				int id = rs.getInt("member_id");
				int times = rs.getInt("SUM(times_recent)");
				itemTimes.put(id, times);
			}
			rs.close();
			ps.close();
			con.close();
		}catch(SQLException e){
			e.printStackTrace();
		}
		//找到最近访问次数的最大数字
		Integer maxTimes = 0;
		for(Integer num : itemTimes.values()){
			if(num > maxTimes){
				maxTimes = num;
			}
		}
				
		//得到最近访问次数中最大数字的位数
		String maxT = "" + maxTimes;
		int maxLen = maxT.length();
				
		//将包含uri个数（items的映射值）乘以maxLen，加上该实体的最近访问次数，得到排序的依据。优先按重复次数排，如果重复次数相同，最近访问越多，排名越靠前
		LinkedList<Entry<Integer, Integer>> toSort = new LinkedList<Entry<Integer, Integer>>(); 
		for(int item : items.keySet()){
			toSort.add(new SimpleEntry<Integer, Integer>(item, ((int)(items.get(item) * Math.pow(10.0, 0.0 + maxLen)) + 
					((itemTimes.get(item) == null) ? 0 : itemTimes.get(item)))));
		}
		
			
		
		Collections.sort(toSort, new NComparator());
				
		//将拍好顺序的collection包装好返回
		int count = 0;
		for(Entry<Integer, Integer> en : toSort){
			int id = en.getKey();
			ret.add(PackingService.pack(id, 1, this.lang));
			count++;
			if(count == requiredNum){
				break;
			}
		}
		return ret;
	}

	
	/*
	public static void main(String[] args){
		CustEntityRelateRecomm rec = new CustEntityRelateRecomm("en");
		try {
			LinkedList<QuadItem> l = rec.getRecommandItems(17, "1");
			for(QuadItem qi : l){
				System.out.println(qi.getId() + " " + qi.getGenre());
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	*/
}
